package com.manage.platform.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PolicyConditions;
import com.aliyun.oss.model.PutObjectRequest;
import com.manage.platform.exception.CommonException;
import com.manage.platform.properties.AliCloudProperties;
import com.manage.platform.utils.R;
import com.manage.platform.service.OssFileService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;


/**
 * @author lk
 * @date 2024/2/22 17:42
 */
@AllArgsConstructor
@Service
public class OssFileServiceImpl implements OssFileService {

     private final AliCloudProperties aliCloudProperties;

    /**
     * 阿里云OSS的上传凭证
     *
     * @return
     */
    @Override
    public R getOssFileToken() {
        //ossClient实例
        OSS ossClient = new OSSClientBuilder().build(aliCloudProperties.getOss().getEndpoint(), aliCloudProperties.getAccessKey(), aliCloudProperties.getSecretKey());
        try {
            // 创建以当天日期命名的目录
            String dir = DateUtil.today();
            // 设置策略过期时间（30分钟）
            long expireTime = 1800;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            // 创建上传策略条件
            PolicyConditions policyConditions = new PolicyConditions();
            // 设置文件大小范围限制（0-100MB）
            policyConditions.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 104857600);
            // 限制上传到指定目录
            policyConditions.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
            // 生成策略和签名
            String postPolicy = ossClient.generatePostPolicy(expiration, policyConditions);
            String encodedPolicy = BinaryUtil.toBase64String(postPolicy.getBytes(StandardCharsets.UTF_8));
            String postSignature = ossClient.calculatePostSignature(postPolicy);
            // 构建响应数据
            Map<String, String> respMap = new LinkedHashMap<>();
            respMap.put("accessId", aliCloudProperties.getAccessKey());
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);
            respMap.put("dir", dir);
            respMap.put("host", aliCloudProperties.getOss().getHost());
            respMap.put("expire", String.valueOf(expireEndTime / 1000));
            return R.ok(respMap);
        } catch (Exception e) {
            throw new CommonException("获取上传令牌失败");
        } finally {
            ossClient.shutdown();
        }
    }

    /**
     * 上传文件
     */
    @Override
    public String ossUploadFile(MultipartFile file) {
        // 参数校验
        if (file == null || file.isEmpty()) {
            throw new CommonException("上传文件不能为空");
        }
        OSS ossClient = new OSSClientBuilder().build(aliCloudProperties.getOss().getEndpoint(), aliCloudProperties.getAccessKey(), aliCloudProperties.getSecretKey());
        try{
            // 获取原始文件名
            String originalFilename = StringUtils.trimToEmpty(file.getOriginalFilename());
            // 生成唯一文件名: 日期目录 + 雪花ID + 文件扩展名
            String fileExtension = StringUtils.isNotBlank(originalFilename) ?
                    originalFilename.substring(originalFilename.lastIndexOf('.')) : "";
            String objectName = String.format("%s/%s%s",
                    DateUtil.today(),
                    IdUtil.getSnowflake(1, 1).nextIdStr(),
                    fileExtension);
            // 创建上传请求
            PutObjectRequest putObjectRequest = new PutObjectRequest(
                    aliCloudProperties.getOss().getBucket(),
                    objectName,
                    file.getInputStream()
            );
            // 可选: 设置元数据
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(file.getSize());
            metadata.setContentType(file.getContentType());
            putObjectRequest.setMetadata(metadata);
            // 执行上传
            ossClient.putObject(putObjectRequest);
            // 返回完整的访问URL
            return String.format("https://%s.%s/%s", aliCloudProperties.getOss().getBucket(), aliCloudProperties.getOss().getEndpoint(), objectName);
        } catch (IOException e) {
            //log.error("读取文件流失败: {}", e.getMessage(), e);
            throw new CommonException("文件读取失败");
        } catch (Exception e) {
            //log.error("OSS文件上传失败: {}", e.getMessage(), e);
            throw new CommonException("文件上传失败，请稍后重试");
        }finally {
            ossClient.shutdown();
        }
    }

    /**
     * 批量上传
     */
    @Override
    public List<String> ossUploadFileList(MultipartFile[] file) {
        final ArrayList<String> list = new ArrayList<>();
        for (MultipartFile multipartFile : file) {
            list.add(ossUploadFile(multipartFile));
        }
        return list;
    }

}
